package com.qiaofang.applet.service.member.service.impl;

import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.common.context.QfContextHolder;
import com.qiaofang.applet.common.exception.BusinessException;
import com.qiaofang.applet.constants.UpDownFlagConstants;
import com.qiaofang.applet.service.member.domain.EmployeeProperty;
import com.qiaofang.applet.service.member.repository.EmployeePropertyRepository;
import com.qiaofang.applet.service.member.service.EmployeePropertyService;
import com.qiaofang.applet.service.member.service.dto.EmployeeHouseNumDto;
import com.qiaofang.applet.service.member.service.dto.EmployeePropertyBatchSaveDto;
import com.qiaofang.applet.service.member.service.dto.EmployeePropertyQueryDto;
import com.qiaofang.applet.service.member.service.dto.EmployeePropertySaveDto;
import com.qiaofang.applet.service.property.domain.FirsthandEstate;
import com.qiaofang.applet.service.property.domain.Property;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author daiyuxiang
 */
@Slf4j
@Service
public class EmployeePropertyServiceImpl extends MongoBaseService<EmployeeProperty, String> implements EmployeePropertyService {

    private final EmployeePropertyRepository repository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private EmployeePropertyRepository employeePropertyRepository;

    @Autowired
    public EmployeePropertyServiceImpl(EmployeePropertyRepository repository) {
        super(repository);
        this.repository = repository;
    }

    @Override
    public List<String> findPropertyListByParams(EmployeePropertyQueryDto queryDto) {
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("employeeUniqueUuid", match -> match.exact())
                .withMatcher("propertyType", match -> match.exact())
                .withMatcher("corporationCode", match -> match.exact())
                .withIgnoreNullValues();

        EmployeeProperty params = new EmployeeProperty();
        BeanUtils.copyProperties(queryDto, params);
        params.setCorporationCode(QfContextHolder.getContext().getCorporationCode());
        List<EmployeeProperty> result = repository.findAll(Example.of(params, matcher));

        return result.stream().map(EmployeeProperty::getPropertyUniqueUuid).collect(Collectors.toList());
    }

    @Override
    public Object saveByParams(EmployeePropertySaveDto saveDto) {
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("employeeUniqueUuid", match -> match.exact())
                .withMatcher("propertyUniqueUuid", match -> match.exact())
                .withMatcher("propertyType", match -> match.exact())
                .withMatcher("corporationCode", match -> match.exact())
                .withIgnoreNullValues();

        EmployeeProperty params = new EmployeeProperty();
        BeanUtils.copyProperties(saveDto, params);
        params.setCorporationCode(QfContextHolder.getContext().getCorporationCode());
        if (repository.findOne(Example.of(params, matcher)).isPresent()) {
            throw new BusinessException("经纪人已经添加过该房源");
        }
        params.setCreateTime(new Date());
        return repository.save(params);
    }


    @Override
    public void batchSaveByParams(EmployeePropertyBatchSaveDto saveDto) {
        List<String> propertyUniqueUuidList = saveDto.getPropertyUniqueUuidList();
        Criteria criteria = Criteria.where("employeeUniqueUuid").is(saveDto.getEmployeeUniqueUuid())
                .and("corporationCode").is(QfContextHolder.getContext().getCorporationCode())
                .and("propertyType").is(saveDto.getPropertyType())
                .and("propertyUniqueUuid").in(propertyUniqueUuidList);
        long count = mongoTemplate.count(new Query(criteria), EmployeeProperty.class);
        if (count > 0){
            throw new BusinessException("经纪人已经添加过房源");
        }
        List<EmployeeProperty> list = new ArrayList<>(propertyUniqueUuidList.size());
        Date createTime = new Date();
        for (String propertyUniqueUuid : propertyUniqueUuidList) {
            EmployeeProperty employeeProperty = EmployeeProperty.builder()
                    .employeeUniqueUuid(saveDto.getEmployeeUniqueUuid())
                    .propertyType(saveDto.getPropertyType())
                    .propertyUniqueUuid(propertyUniqueUuid)
                    .build();
            employeeProperty.setCorporationCode(QfContextHolder.getContext().getCorporationCode());
            employeeProperty.setCreateTime(createTime);
            list.add(employeeProperty);
        }
        repository.saveAll(list);
    }


    @Override
    public void removeByParams(EmployeePropertySaveDto saveDto) {
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("employeeUniqueUuid", match -> match.exact())
                .withMatcher("propertyUniqueUuid", match -> match.exact())
                .withMatcher("propertyType", match -> match.exact())
                .withMatcher("corporationCode", match -> match.exact())
                .withIgnoreNullValues();

        EmployeeProperty params = new EmployeeProperty();
        BeanUtils.copyProperties(saveDto, params);
        params.setCorporationCode(QfContextHolder.getContext().getCorporationCode());
        Optional<EmployeeProperty> optional = repository.findOne(Example.of(params, matcher));
        if (optional.isPresent()) {
            repository.delete(optional.get());
        }
    }

    @Override
    public String getOpFlag(EmployeePropertySaveDto saveDto) {
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("employeeUniqueUuid", match -> match.exact())
                .withMatcher("propertyUniqueUuid", match -> match.exact())
                .withMatcher("propertyType", match -> match.exact())
                .withMatcher("corporationCode", match -> match.exact())
                .withIgnoreNullValues();

        EmployeeProperty params = new EmployeeProperty();
        BeanUtils.copyProperties(saveDto, params);
        params.setCorporationCode(QfContextHolder.getContext().getCorporationCode());
        Optional<EmployeeProperty> optional = repository.findOne(Example.of(params, matcher));
        if (optional.isPresent()) {
            return "remove";
        }
        return "add";
    }

    @Override
    public EmployeeHouseNumDto getEmployeeHouseNum(String employeeUniqueUuid) {
        EmployeeHouseNumDto employeeHouseNumDto = new EmployeeHouseNumDto();
        List<EmployeeProperty> list = employeePropertyRepository.findByEmployeeUniqueUuid(employeeUniqueUuid);
        List<String> firstList = new LinkedList<>();
        List<String> saleList = new LinkedList<>();
        List<String> rentList = new LinkedList<>();
        for (EmployeeProperty employeeProperty : list) {
            switch (employeeProperty.getPropertyType()) {
                case "新房":
                    firstList.add(employeeProperty.getPropertyUniqueUuid());
                    break;
                case "二手房":
                    saleList.add(employeeProperty.getPropertyUniqueUuid());
                    break;
                case "租房":
                    rentList.add(employeeProperty.getPropertyUniqueUuid());
                    break;
            }
        }
        Criteria criteriaFirst = Criteria.where("estateUniqueUuid").in(firstList)
                .and("upDownFlag").is(UpDownFlagConstants.UP_FLAG.getValue())
                .and("averagePrice").ne(null);

        Criteria criteriaSale = Criteria.where("propertyUniqueUuid").in(saleList)
                .and("upDownFlag").is(UpDownFlagConstants.UP_FLAG.getValue())
                .and("square").ne(null)
                .and("sellPrice").ne(null)
                .and("sellUnitPrice").ne(null);

        Criteria criteriaRent = Criteria.where("propertyUniqueUuid").in(rentList)
                .and("upDownFlag").is(UpDownFlagConstants.UP_FLAG.getValue())
                .and("square").ne(null)
                .and("rentPrice").ne(null)
                /*.and("rentUnitPrice").ne(null)*/;
        employeeHouseNumDto.setFirsthandEstateNum(mongoTemplate.count(new Query(criteriaFirst), FirsthandEstate.class));
        employeeHouseNumDto.setSaleNum(mongoTemplate.count(new Query(criteriaSale), Property.class));
        employeeHouseNumDto.setRentNum(mongoTemplate.count(new Query(criteriaRent), Property.class));
        return employeeHouseNumDto;
    }

    /**
     * 获取经纪人上架二手房时间顺序
     *
     * @param propertyUniqueUuid
     * @param showNum
     * @return
     */
    @Override
    public List<String> getPutAwayOrder(String propertyUniqueUuid, String companyUuid, int showNum, int type) {
        Query query = new Query().addCriteria(Criteria.where("propertyUniqueUuid").is(propertyUniqueUuid));
        if (type == 1){
            query.addCriteria(Criteria.where("propertyType").is("新房"));
        }else {
            query.addCriteria(Criteria.where("propertyType").ne("新房"));
        }
        query.with(Sort.by(Sort.Order.asc("createTime")));
        query.skip(0).limit(showNum);
        List<EmployeeProperty> list = mongoTemplate.find(query, EmployeeProperty.class);
        List<String> employeeUuidList = new ArrayList<>();
        for (EmployeeProperty employeeProperty : list) {
            String employeeUniqueUuid = employeeProperty.getEmployeeUniqueUuid();
            if (StringUtils.isEmpty(employeeUniqueUuid)) {
                continue;
            }
            String employeeUuid = employeeUniqueUuid.replaceAll(companyUuid + "_", "");
            employeeUuidList.add(employeeUuid);

        }
        return employeeUuidList;
    }
}
